package com.gw.business.analysis.task;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.gw.business.analysis.model.UserTrackBasic;
import com.gw.business.analysis.model.UserTrackDataDetail;
import com.gw.business.analysis.service.UserTrackBasicService;
import com.gw.business.analysis.service.UserTrackDataDetailService;
import com.gw.business.common.util.DateUtil;
import com.gw.platform.logger.Log;
import com.gw.platform.util.DateUtils;

/**
 * 
 * 类功能:用户访问详细统计
 *  
 * <p>功能描述：通过对流水数据user_track_basic 表的数据，
 * 				求的某个用户ID+媒介+来源，
 * 				访问时长在30分钟以内的统计数据。
 *
 *	特殊字段处理：behavior_type 只保存咨询和访问 也就是（1,2） 
 *			      当用户其他行为的时候 不记录并把账号放入  
 *				  behavior_detail_type  字段中
 * </p>
 * 
 * <p>
 * 创建者:关博
 * </p>
 * <p>
 * 创建时间:2015-03-02
 * </p>
 * <p>
 * 修改者:
 * </p>
 * <p>
 * 修改时间:
 * </p>
 * <p>
 * 修改原因：
 * </p>
 * <p>
 * 审核者:
 * </p>
 * <p>
 * 审核时间:
 * </p>
 * <p>
 * 审核意见：
 * </p>
 * 
 * 
 * 	详细汇总表：每隔5分钟统计一次
	
	点击异常：每2分钟执行一次
	
	行为统计：每隔8分钟统计一次
	来源媒介统计：每隔8分钟统计一次
	
	来源媒介效果表：每天凌晨4点统计一次
	
	平均：每月1号凌晨0点10分执行
	
	点击异常：每隔10分钟统计一次
	注册异常：每隔30分钟统计一次
 * 
 */
@Component
public class UserTrackDataDetailTask {
	
	@Resource
	private UserTrackBasicService  userTrackBasicService;
	
	@Resource
	private UserTrackDataDetailService  userTrackDataDetailService;
	
	/**
	 * 30分钟
	 */
	private final int MINUTES = 30;
	
	/**单位：秒 
	 * 30分钟 访问时长的范围
	 */
	private final int SECONDS = 1000 * 60 * MINUTES;
	
	
	/**
	 * 通过分析 basic  初始化dateDetail表。
	 * 任务每间隔30分钟执行一次
	 */
	//@Scheduled(cron = "* 0/15 * * * ?")
	@Scheduled(cron = "0/300 * * * * ?")
    public void InitDate(){
		
		Log.info(this.getClass(), "UserTrackDataDetailTask开始-->");
		
		long start = System.currentTimeMillis();
		/**
		 * 1.获取当前时间往后推30分钟数据， 然后根据detail已存在的数据做比对，满足时长的条件进行update 或者 insert操作
		 */
		//存储detail表中，end_time（数据结构字段）大于当前时间-MIN时间的数据列表 （key：userid_来源_媒介）
		Map<String,UserTrackDataDetail> detialOldDataMap = new HashMap<String, UserTrackDataDetail>();
		
		//需要更新的数据列表（key 用户ID_来源_媒介）
		Map<String,UserTrackDataDetail> needUpdateDataMap = new HashMap<String, UserTrackDataDetail>();
		
		//需要入库的数据列表（key 用户ID_来源_媒介）
		Map<String,List> needInsertDataMap = new HashMap<String, List>();
		
		//时间间隔（当前时间30分钟之前的数据）
		Date  halfTime=DateUtil.addMinutes(new Date(), -MINUTES * 2);
		String strHalfTime=DateUtil.toYyyymmddHhmmss(halfTime);
		
		//获取基础数据列表，visit_time（数据结构字段）大于当前时间-MIN时间的数据列表
		List<UserTrackBasic> basicItemList = userTrackBasicService.getGtVisitTime(strHalfTime);
		//获取详细数据列表，end_time（数据结构字段）大于当前时间-MIN时间的数据列表
		List<UserTrackDataDetail> detailOldList = userTrackDataDetailService.findEndTimeBigUser(strHalfTime);
		
		//存储旧数据(以前分析过的数据)这是新旧对象对比的关键  key：userid_来源_媒介_年-月-日(第二天的重新算不能是一个会话)
		for (UserTrackDataDetail d : detailOldList) {
			detialOldDataMap.put(d.getUserId() + "_" + d.getUtmcsr() + "_" + d.getUtmcmd() + "_" + DateUtils.formatDateToString(d.getEndTime(), "yyyy-MM-dd"), d);
		}
		
		//遍历基础数据列表
		for (UserTrackBasic u : basicItemList) {
			if(detialOldDataMap.size() > 0){
				//基础数据生成key 在旧数据MAP中查找是否有重数据,有->就判断值是否不同，  没有->把这个基础数据视为新数据放入待insert Map中.
				String key = u.getUserId() + "_" + u.getUtmcsr() + "_" + u.getUtmcmd() + "_" + DateUtils.formatDateToString(u.getVisitTime(), "yyyy-MM-dd");
				UserTrackDataDetail  u_old = detialOldDataMap.get(key);
				//detail最后时间小于 新数据的访问时间就分析,不然跳过脏数据
				if(u_old!=null){
					if(u_old.getEndTime().getTime() < u.getVisitTime().getTime()){
								long middleTime = u.getVisitTime().getTime() - u_old.getEndTime().getTime();
								if(middleTime > SECONDS){  //超过半小时的   insert
									insertNeedsortDate(needInsertDataMap,u);
								}else{//不超过的  update
									u_old.setTimeLength(DateUtil.timeLengthAppend(u_old.getEndTime(), u.getVisitTime(),u_old.getTimeLength()));
									u_old.setEndTime(u.getVisitTime());
									//访问或者咨询
									if(u.getBehaviorType().equals("1") || u.getBehaviorType().equals("2")){
										if(!u_old.getBehaviorType().contains(u.getBehaviorType())){
											u_old.setBehaviorType(createBehaviorType(u_old.getBehaviorType(),u.getBehaviorType()));
										}
										
									}else{
										if(!u_old.getBehaviorDetailType().contains(u.getBehaviorDetailType())){
											u_old.setBehaviorDetailType(strJoin(u_old.getBehaviorDetailType(),u.getBehaviorDetailType()));
										}
									}
									
									//PD 只显示第一个数据
			//						old_date.setIp(u.getIp());
			//						old_date.setUtmcsr(u.getUtmcsr());
			//						old_date.setUtmctr(u.getUtmctr());
									u_old.setMarkWords(strJoin(u_old.getMarkWords(),u.getMarkWords()));
			//						old_date.setUtmccn(u.getUtmccn());
			//						old_date.setUtmcct(u.getUtmcct());
			//						old_date.setUtmcmd(u.getUtmcmd());
									u_old.setBrowserCount(u_old.getBrowserCount()+u.getBrowserCount());
									u_old.setVisitCount(u_old.getVisitCount()+u.getVisitCount());
									u_old.setAdvisoryCount(u_old.getAdvisoryCount()+u.getAdvisoryCount());
									u_old.setDemoCount(u_old.getDemoCount()+u.getDemoCount());
									u_old.setRealCount(u_old.getRealCount()+u.getRealCount());
									u_old.setDepositCount(u_old.getDepositCount()+u.getDepositCount());
									u_old.setUrl(u_old.getUrl()+", "+u.getUrl());
									
									needUpdateDataMap.put(u_old.getUserId(), u_old);
								}
					}else{ //脏数据跳过
						continue;
					}
				}else{ //不存在的数据  insert
					insertNeedsortDate(needInsertDataMap,u);
				}
			}else{//无数据的情况下  insert
				insertNeedsortDate(needInsertDataMap,u);
			}
		}
		
		Log.info(this.getClass(), "needInsertDataMap-->" + needInsertDataMap.size());
		Log.info(this.getClass(), "needUpdateDataMap-->" + needUpdateDataMap.size());

		//对数据分析后， 对needInsertDataMap里的base进行合并后insert
		Map<String,UserTrackDataDetail>  endInsertMap=new HashMap<String, UserTrackDataDetail>();
		
		Iterator<String>  its= needInsertDataMap.keySet().iterator();
		while(its.hasNext()){
			List<UserTrackBasic> items = needInsertDataMap.get(its.next());
			 UserTrackDataDetail temp=null;
			 for (int i = 0; i < items.size(); i++) {
				 UserTrackBasic b=items.get(i);
				 String key = b.getUserId() + "_" + b.getUtmcsr() + "_" + b.getUtmcmd()+ "_" + DateUtils.formatDateToString(b.getVisitTime(), "yyyy-MM-dd");
				if(i==0){
					temp=new UserTrackDataDetail();
					temp.setUserId(b.getUserId());
					temp.setAdvisoryCount(b.getAdvisoryCount());
					//访问和咨询
					if(b.getBehaviorType().equals("1") || b.getBehaviorType().equals("2")){
						temp.setBehaviorType(b.getBehaviorType());
 						temp.setBehaviorDetailType("");
						
					}else{
 						temp.setBehaviorType("");
						temp.setBehaviorDetailType(b.getBehaviorDetailType());
					}
					
					temp.setBrowserCount(b.getBrowserCount());
					temp.setDemoCount(b.getDemoCount());
					temp.setDepositCount(b.getDepositCount());
					temp.setStartTime(b.getVisitTime());
					temp.setEndTime(b.getVisitTime());
					temp.setIp(b.getIp());
					temp.setMarkWords(b.getMarkWords());
					temp.setRealCount(b.getRealCount());
					temp.setSort(b.getSort());
					temp.setTimeLength("0\"00");
					temp.setUrl(b.getUrl());
					temp.setVisitCount(b.getVisitCount());
					temp.setUtmcsr(b.getUtmcsr());
					temp.setUtmctr(b.getUtmctr());
					temp.setUtmccn(b.getUtmccn());
					temp.setUtmcct(b.getUtmcct());
					temp.setUtmcmd(b.getUtmcmd());
					temp.setPlatformType(b.getPlatformType());
					endInsertMap.put(key, temp);
				}else{
					//查看Map中是否有Key的内容
					UserTrackDataDetail map_temp_Obj = endInsertMap.get(key);   
					
					if(map_temp_Obj !=null && map_temp_Obj.getEndTime().getTime() < b.getVisitTime().getTime()){
						long middleTime=b.getVisitTime().getTime() - map_temp_Obj.getEndTime().getTime();
						if(middleTime > SECONDS){  //超过半小时的   insert
							temp=new UserTrackDataDetail();
							temp.setUserId(b.getUserId());
							temp.setAdvisoryCount(b.getAdvisoryCount());
							temp.setBehaviorDetailType(b.getBehaviorDetailType());
							//访问和咨询
							if(b.getBehaviorType().equals("1") || b.getBehaviorType().equals("2")){
								temp.setBehaviorType(b.getBehaviorType());
 								temp.setBehaviorDetailType("");
								
							}
							else{
 								temp.setBehaviorType("");
								temp.setBehaviorDetailType(b.getBehaviorDetailType());
							}
							temp.setBrowserCount(b.getBrowserCount());
							temp.setDemoCount(b.getDemoCount());
							temp.setDepositCount(b.getDepositCount());
							temp.setStartTime(b.getVisitTime());
							temp.setEndTime(b.getVisitTime());
							temp.setIp(b.getIp());
							temp.setMarkWords(b.getMarkWords());
							temp.setRealCount(b.getRealCount());
							temp.setSort(b.getSort());
							temp.setTimeLength("0\"00");
							temp.setUrl(b.getUrl());
							temp.setVisitCount(b.getVisitCount());
							temp.setUtmcsr(b.getUtmcsr());
							temp.setUtmctr(b.getUtmctr());
							temp.setUtmccn(b.getUtmccn());
							temp.setUtmcct(b.getUtmcct());
							temp.setUtmcmd(b.getUtmcmd());
							temp.setPlatformType(b.getPlatformType());
							endInsertMap.put(key, map_temp_Obj);  //添加新值
						}else{//不超过的  update end time
							map_temp_Obj.setTimeLength(DateUtil.timeLengthAppend(map_temp_Obj.getEndTime(), b.getVisitTime(),map_temp_Obj.getTimeLength()));
							map_temp_Obj.setEndTime(b.getVisitTime());
							
							//访问或者咨询
							if(b.getBehaviorType().equals("1") || b.getBehaviorType().equals("2")){
								if(!map_temp_Obj.getBehaviorType().contains(b.getBehaviorType())){
									map_temp_Obj.setBehaviorType(createBehaviorType(map_temp_Obj.getBehaviorType(),b.getBehaviorType()));
								}
								
							}else{
								if(!map_temp_Obj.getBehaviorDetailType().contains(b.getBehaviorDetailType())){
									map_temp_Obj.setBehaviorDetailType(strJoin(map_temp_Obj.getBehaviorDetailType(),b.getBehaviorDetailType()));
								}
							}
                                                                                                                      							
							//PD 只显示第一个数据
//							map_temp_Obj.setIp(b.getIp());
//							map_temp_Obj.setUtmcsr(b.getUtmcsr());
//							map_temp_Obj.setUtmctr(b.getUtmctr());
							map_temp_Obj.setMarkWords(strJoin(map_temp_Obj.getMarkWords(),b.getMarkWords()));
//							map_temp_Obj.setUtmccn(b.getUtmccn());
//							map_temp_Obj.setUtmcct(b.getUtmcct());
//							map_temp_Obj.setUtmcmd(b.getUtmcmd());
							map_temp_Obj.setBrowserCount(map_temp_Obj.getBrowserCount()+b.getBrowserCount());
							map_temp_Obj.setVisitCount(map_temp_Obj.getVisitCount()+b.getVisitCount());
							map_temp_Obj.setAdvisoryCount(map_temp_Obj.getAdvisoryCount()+b.getAdvisoryCount());
							map_temp_Obj.setDemoCount(map_temp_Obj.getDemoCount()+b.getDemoCount());
							map_temp_Obj.setRealCount(map_temp_Obj.getRealCount()+b.getRealCount());
							map_temp_Obj.setDepositCount(map_temp_Obj.getDepositCount()+b.getDepositCount());
							map_temp_Obj.setUrl(map_temp_Obj.getUrl()+ ", " + b.getUrl());
							endInsertMap.put(key, map_temp_Obj);  //覆盖原值
						}
					}
				}
				
			}
		}
		
		Log.info(this.getClass(), "endInsertMap-->" + endInsertMap.size());
		//needUpdateDataMap  更新sql 执行
		//endInsertMap   插入SQL 执行
	    Iterator<String> updateObjKeys=needUpdateDataMap.keySet().iterator();
		while(updateObjKeys.hasNext()){
			String key=updateObjKeys.next();
//			UserTrackDataDetail map_temp_Obj = needUpdateDataMap.get(key);
//			if(map_temp_Obj != null){
//				if(!map_temp_Obj.getBehaviorDetailType().equals("")){
//					map_temp_Obj.setBehaviorType("");
//				}
//			}
			userTrackDataDetailService.update(needUpdateDataMap.get(key));
		}
		
		Iterator<String> insertObjKeys= endInsertMap.keySet().iterator();
		while (insertObjKeys.hasNext()) {
			String key=insertObjKeys.next();
//			UserTrackDataDetail map_temp_Obj = endInsertMap.get(key);
//			if(map_temp_Obj != null){
//				if(!map_temp_Obj.getBehaviorDetailType().equals("")){
//					map_temp_Obj.setBehaviorType("");
//				}
//			}
			userTrackDataDetailService.insert(endInsertMap.get(key));
		}
		
		Log.info(this.getClass(), "UserTrackDataDetailTask结束，执行时间(s)：-->" + (System.currentTimeMillis()-start)/1000);
		
	}
	
	/**
	 * 拼接前后值
	 * @param one
	 * @param two
	 * @return
	 */
	private String strJoin(String one,String two){
		if(one==null) one="";
		if(two==null) two="";
		
		if(one.equals("")){
			return two;
		}else if(two.equals("")){
			return one;
		}else{
			return one+","+two;
		}
	}
	
	/**
	 * 对要生成的 basic  提取出来放入 map中 每个用户一个对应的排序list  后面计算后插入detail  
	 * @param needInsertDataMap
	 * @param u
	 */
	private void insertNeedsortDate(Map<String,List> needInsertDataMap,UserTrackBasic u){
		String key = u.getUserId() + "_" + u.getUtmcsr() + "_" + u.getUtmcmd() + "_" + DateUtils.formatDateToString(u.getVisitTime(), "yyyy-MM-dd");
		
		List items= needInsertDataMap.get(key);
		if(items!=null){
			items.add(u);
		}else{
			items=new ArrayList<UserTrackDataDetail>();
			items.add(u);
		}
		needInsertDataMap.put(key, items);
	}
	
	/**
	 * 访问(1)、咨询(2)、模拟开户(3)、真实开户(4)、首次入金(5)    
	 * 有 2 3 4 5  1不显示           
	 * 同时因为(3.4.5 通过不断累加 behavior_detail_type 即可)所以也不要累加进去  
	 * 只会出1或者2或者空值（‘’）
	 * @param source
	 * @param join
	 * @return
	 */
	private String createBehaviorType(String source,String join){
		if(source==null||source.length()==0){
			if(join!=null&&join.equals("2")||join.equals("1"))
				return join;
		}
		
		int join_int=0;
		try{
			join_int=Integer.parseInt(join);
		}catch (Exception e) {
			return source;
		}
		
		if(join_int==1){ //如果等于1 ，就要判断原来的数据有没有2  没有累加 有只返回2 其他号码不返回
			if(!(source.indexOf("2")>=0)){
				source=source+","+join;
			}
			return source;
		}else{//当join不等于1的情况下 检查源数据是否包含1，有就返回2（3.4.5跳过）  没有只和2累加 （3.4.5跳过）
			 if(source.indexOf("1")>=0){
				 if(join_int==2) return join;else return"";
			 }else{
				 if(join_int==2)return source=source+","+join;else return source;
			 }
		}
	}
	
}